﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CoachingOrganizer.Database.DataAccess;
using CoachingOrganizer.Toolkit.Events;
using CoachingOrganizer.ClientInfrastructure.ServicesEntities.LocalStorage.Tools.MoneyCalculation;
using System.Threading.Tasks;

namespace CoachingOrganizer.Database.DataAccessLayer.Tools.MoneyCalculation
{
    public class MoneyCalculationDAL : ToolDALBase, IMoneyCalculationInfo
    {
        private readonly List<StableMoneyFlowItemDAL> _stableItems = new List<StableMoneyFlowItemDAL>();
        private readonly List<OccasionalMoneyFlowItemDAL> _occasionalItems = new List<OccasionalMoneyFlowItemDAL>();
        private MoneyCalculationDA _da;
        public DateTime _start;
        public DateTime _finish;
        private TimeSpan _period;

        public DateTime Start
        {
            get { return _start; }
            set { _start = value; }
        }

        public DateTime Finish
        {
            get { return _finish; }
            set { _finish = value; }
        }

        public List<StableMoneyFlowItemDAL> StableItems
        {
            get { return _stableItems; }
        }

        public List<OccasionalMoneyFlowItemDAL> OccasionalItems
        {
            get { return _occasionalItems; }
        }
        public IEnumerable<IStableMoneyFlowItemInfo> StableItemsInfo
        {
            get { return _stableItems; }
        }

        public IEnumerable<IOccasionalMoneyFlowItemInfo> OccasionalItemsInfo
        {
            get { return _occasionalItems; }
        }

        public MoneyCalculationDAL(DbManagerBase dbManager)
            : base(dbManager)
        {

        }

        public override object CreateNewDA(GoalDA goal)
        {
            return _da = new MoneyCalculationDA
            {
                GoalId = goal.Id,
                Start = _start,
                Finish = _finish
            };
        }

        public override ActionResult Save()
        {
            _da.Start = _start;
            _da.Finish = _finish;
            return _dbManager.SafeRun(() => _dbManager.Context.InsertOrReplace(_da));
        }

        public bool Load(int id)
        {
            MoneyCalculationDA calculation = _dbManager.Context.Find<MoneyCalculationDA>(da => da.Id == id);
            if (calculation == null)
                return false;
            Load(calculation);
            return true;
        }

        public void Load(MoneyCalculationDA moneyCalculation)
        {
            _da = moneyCalculation;
            _start = moneyCalculation.Start;
            _finish = moneyCalculation.Finish;
            LoadStableItems();
            LoadOccasionalItems();
        }

        public override ActionResult Remove()
        {
            if (_da != null)
                return _dbManager.SafeRun(() => _dbManager.Context.Delete<MoneyCalculationDA>(_da.Id));
            return ActionResult.GetErrorResult(new KeyNotFoundException());
        }

        public ActionResult<IStableMoneyFlowItemInfo> AddNewStableItem(Action<IStableMoneyFlowItemInfo> initCallback)
        {
            StableMoneyFlowItemDAL newMoneyFlowItem = CreateNewStableItem();
            if (initCallback != null)
                initCallback(newMoneyFlowItem);
            ActionResult addResult = AddStableItem(newMoneyFlowItem);
            return addResult.IsValid ? ActionResult<IStableMoneyFlowItemInfo>.GetValidResult(newMoneyFlowItem) : ActionResult<IStableMoneyFlowItemInfo>.GetErrorResult(addResult);
        }

        public ActionResult<IOccasionalMoneyFlowItemInfo> AddNewOccasionalItem(Action<IOccasionalMoneyFlowItemInfo> initCallback)
        {
            OccasionalMoneyFlowItemDAL newMoneyFlowItem = CreateNewOccasionalItem();
            if (initCallback != null)
                initCallback(newMoneyFlowItem);
            ActionResult addResult = AddOccasionalItem(newMoneyFlowItem);
            return addResult.IsValid ? ActionResult<IOccasionalMoneyFlowItemInfo>.GetValidResult(newMoneyFlowItem) : ActionResult<IOccasionalMoneyFlowItemInfo>.GetErrorResult(addResult);
        }

        public StableMoneyFlowItemDAL CreateNewStableItem()
        {
            return new StableMoneyFlowItemDAL(_dbManager);
        }

        public OccasionalMoneyFlowItemDAL CreateNewOccasionalItem()
        {
            return new OccasionalMoneyFlowItemDAL(_dbManager);
        }

        public ActionResult AddStableItem(StableMoneyFlowItemDAL moneyFlowItem)
        {
            _stableItems.Add(moneyFlowItem);
            return _dbManager.SafeRun(() => _dbManager.Context.Insert(moneyFlowItem.CreateNewDA(_da)));
        }

        public ActionResult AddOccasionalItem(OccasionalMoneyFlowItemDAL moneyFlowItem)
        {
            _occasionalItems.Add(moneyFlowItem);
            return _dbManager.SafeRun(() => _dbManager.Context.Insert(moneyFlowItem.CreateNewDA(_da)));
        }

        public ActionResult LoadStableItems()
        {
            return _dbManager.SafeRun(() =>
            {
                foreach (StableMoneyFlowItemDA moneyFlowItemDA in _dbManager.Context.Table<StableMoneyFlowItemDA>().Where(g => g.MoneyCalculationId == _da.Id).ToArray())
                {
                    StableMoneyFlowItemDAL moneyFlowItem = new StableMoneyFlowItemDAL(_dbManager);
                    moneyFlowItem.Load(moneyFlowItemDA);
                    _stableItems.Add(moneyFlowItem);
                }
            });
        }

        public ActionResult LoadOccasionalItems()
        {
            return _dbManager.SafeRun(() =>
            {
                foreach (OccasionalMoneyFlowItemDA moneyFlowItemDA in _dbManager.Context.Table<OccasionalMoneyFlowItemDA>().Where(g => g.MoneyCalculationId == _da.Id).ToArray())
                {
                    OccasionalMoneyFlowItemDAL moneyFlowItem = new OccasionalMoneyFlowItemDAL(_dbManager);
                    moneyFlowItem.Load(moneyFlowItemDA);
                    _occasionalItems.Add(moneyFlowItem);
                }
            });
        }
    }
}